package com.sub.dbRouting;

import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.sub.dbRouting.annotation.RouterConstants;
import com.sub.dbRouting.annotation.RwRouter;

/**
 * @Description: TODO(切面切点 在Router注解的方法执行前执行 切点织入 读写分离)
 * @author wangkai
 * @date 2018年5月31日
 *
 */
@Aspect
@Component
public class DBRouterRwInterceptor {

	private static final Logger log = LoggerFactory.getLogger(DBRouterRwInterceptor.class);

	private DBRwRouter dBRwRouter;

	private static final String REGEX = "insert*?|delete*?|update*?";

	@Pointcut("@annotation(com.sub.dbRouting.annotation.RwRouter)")
	public void aopPoint() {

	}

	@Before("aopPoint()")
	public Object doRoute(JoinPoint jp) throws Throwable {
		long t1 = System.currentTimeMillis();
		boolean result = true;
		Method method = getMethod(jp);
		RwRouter router = method.getAnnotation(RwRouter.class);
		String routeField = router.value();
		if (routeField != null && routeField.trim().length() > 0) {
			if (routeField.trim().matches(REGEX)) {
				dBRwRouter.doRouteByResource(RouterConstants.ROUTER_TYPE_MASTER);
			} else if (routeField.trim().matches("select*?")) {
				dBRwRouter.doRouteByResource(RouterConstants.ROUTER_TYPE_SLAVE);
			}
		}
		log.debug("doRouteTime{}",(System.currentTimeMillis() - t1));
		return result;
	}

	private Method getMethod(JoinPoint jp) throws NoSuchMethodException {
		Signature sig = jp.getSignature();
		MethodSignature msig = (MethodSignature) sig;
		return getClass(jp).getMethod(msig.getName(), msig.getParameterTypes());
	}

	private Class<? extends Object> getClass(JoinPoint jp) throws NoSuchMethodException {
		return jp.getTarget().getClass();
	}

	public DBRwRouter getdBRwRouter() {
		return dBRwRouter;
	}

	public void setdBRwRouter(DBRwRouter dBRwRouter) {
		this.dBRwRouter = dBRwRouter;
	}

}
